// 函数的声明
// 1.写法1
// void代表返回空值
function fn(a: number, b: string): void {

}

function fn1(a: number, b: string): number {
    return 2
}

// 2.写法2
const fn2 = function (a: number, b: number) {

}

const fn3: (a: number) => number = function (a) {
    return 2
}

fn3(2)

// 最完整写法
// 这不是箭头函数，是语法的声明
const fn4: (a: number) => number = function (a: number): number {
    return 2
}

const fn5: (a: number) => number = (b: number): number => 20

// 3. 写法3，利用接口实现对函数的声明
interface IFunc {
    // (a:number)是形参，:number是返回值
    (a: number, b: number): number,
}

const fn6: IFunc = (a, b) => a * b * 2

fn6(10, 2) //40

//  4. 接口中具备方法
interface IPerson {
    name: String,
    // () => void是类型，把函数类型传给了某个属性
    sayHello: () => void
}

let p: IPerson = {
    name: "sd",
    sayHello() {
        console.log(this.name)
    }

}

interface IPerson2 {
    name: String,
    // 这是个方法，方法返回值是void类型
    sayHello(): void
}

let p1: IPerson2 = {
    name: "sd",
    sayHello() {
        console.log(this.name)
    }

}


// 可选参数和默认值 ，声明函数函数 可选参数和默认值参数 放在参数右边


// 参数类型和数量要严格匹配
function sum(a: number, b: number) {
    return a + b
}

sum(1, 2)

// 写法1
function sum1(a: number, b?: number) {
    // return a + b   b作为可选参数 类型  number | undefined，
    // a + undefined是不可以的
    if (typeof b === "number") {
        return a + b
    } else {
        return a
    }

}

// 写法2，还可以利用函数参数的默认值
function sum2(a: number, b: number = 0) {
    return a + b

}

// 剩余参数的使用,一个函数中 只能有一个剩余参数...args，剩余参数一定要是最右侧的参数
// 前面放三点就可以产生长度可变的参数
// 这个args随便命名

// ...args是...[1,2,3],与1, 2, 3对等,args是[1,2,3]
function add(...args: number[]) {
    // prev 表示上一次调用回调时的返回值，或者初始值 init;刚开始为0
    // cur 表示当前正在处理的数组元素；刚开始为第一个值
    return args.reduce((prev, current) => prev + current)

}
add(1, 2, 3)


// 函数的重载
function reverse(arg: string | number): string | number {
    if (typeof arg === "string") {
        // split() 方法用于把一个字符串分割成字符串数组。,加''就可以每个字符都被分割，不然就是一整个
        // reverse() 方法反转数组中元素的顺序。
        // join() 方法将数组作为字符串返回。元素将由指定的分隔符分隔。默认分隔符是逗号 (,)
        return arg.split("").reverse().join("")
    } else {
        // toString() 方法可把一个 Number 对象转换为一个字符串，并返回结果
        return Number(arg.toString().split("").reverse().join(""))
    }
}


function fn9(a: number) {
    alert("aa");
}

fn9(4)

// 唯一用途
let fn8: () => void = () => console.log("hh")

// 任意类型
let a: any = "six";
a = 7

// 8. never类型  绝不会被访问到的类型
function Never(): never {
    throw new Error()
}

// 死循环也是never

// let neverNum:never = true

// arg只是一个参数，只能传一个值,...args就是可以让其传多个值
function check(arg: number | string) {
    if (typeof arg === "number") {
        console.log("number")
    } else if (typeof arg === "string") {
        console.log("string")
    } else {
        // 把传进来的arg赋值给一个never类型的变量，不行，报错
        const f: never = arg
    }

}

export default null